﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Timers;
using Microsoft.ServiceBus;
using nwrole.plugin;

namespace nwrole.lib {
    public class OrchestratorWebsiteChannel : IOrchestratorWebsiteContract {

        private IOrchestratorWebsiteChannel channel;
        private Timer masterConnectionTimer = new Timer();

        private Guid websiteId;
        private string displayName;

        public OrchestratorWebsiteChannel(Guid websiteId, string displayName) {
            masterConnectionTimer.Elapsed += OnMasterConnectionTimer;
            masterConnectionTimer.Interval = 60 * 1000;

            this.websiteId = websiteId;
            this.displayName = displayName;

            ConnectToOrchestrator();
        }

        public void ConnectToOrchestrator() {
            try {
                ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.AutoDetect;

                Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", "nwrole",
                                                                        "orchestrator/website");

                //Console.WriteLine("Connecting to {0} address: {1}", DeployContext.Config.DeployName, serviceUri);

                TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();

                sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider("owner", "Km+nny0pbfguRgaHjslR/IkWpUprTzgrJYZwvXiCJwU=");
                /*sharedSecretServiceBusCredential.CredentialType = TransportClientCredentialType.SharedSecret;
                sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerName = "owner";
                sharedSecretServiceBusCredential.Credentials.SharedSecret.IssuerSecret = "Km+nny0pbfguRgaHjslR/IkWpUprTzgrJYZwvXiCJwU=";*/

                //ChannelFactory<IOrchestratorChannel> channelFactory = new ChannelFactory<IOrchestratorChannel>();
                ChannelFactory<IOrchestratorWebsiteChannel> channelFactory = new ChannelFactory<IOrchestratorWebsiteChannel>();
                channelFactory.Endpoint.Address = new EndpointAddress(serviceUri);
                channelFactory.Endpoint.Binding = new NetTcpRelayBinding();
                channelFactory.Endpoint.Contract.ContractType = typeof(IOrchestratorWebsiteChannel);

                channelFactory.Endpoint.Behaviors.Add(sharedSecretServiceBusCredential);

                channel = channelFactory.CreateChannel();
                channel.Open();

                channel.Faulted += orchestratorChannel_Faulted;
                channel.Closed += orchestratorChannel_Closed;

            } catch {
                channel = null;
            }

            if (channel == null) {

                masterConnectionTimer.Start();
            }
            else {
                RegisterWebsite(websiteId, displayName);
            }
        }

        private void orchestratorChannel_Closed(object sender, EventArgs e) {
            OrchestratorChannelDisconnected();
        }

        private void orchestratorChannel_Faulted(object sender, EventArgs e) {
            OrchestratorChannelDisconnected();
        }

        private void OrchestratorChannelDisconnected() {
            channel = null;
            masterConnectionTimer.Start();
        }

        private void OnMasterConnectionTimer(object source, ElapsedEventArgs e) {
            masterConnectionTimer.Stop();
            ConnectToOrchestrator();
        }

        /// <summary>
        /// Register a website name with its guid in the Orchestrator. No need to call this method as this class does it automatically upon successfull connection.
        /// </summary>
        /// <param name="websiteId">The website guid</param>
        /// <param name="displayName">The website display name</param>
        public void RegisterWebsite(Guid websiteId, string displayName) {
            if (channel != null) {
                try {
                    channel.RegisterWebsite(websiteId, displayName);
                } catch {
                    OrchestratorChannelDisconnected();
                }
            }
        }

        public void Log(NwroleObjectType? objectType, Guid? objectId, LogLevel level, string message, Exception ex) {
            if (channel != null) {
                try {
                    channel.Log(objectType, objectId, level, message, ex);
                } catch {
                    OrchestratorChannelDisconnected();
                }
            }
        }
    }
}
